package com.yonyou.pmclouds.plan.rmiimpl;

import com.alibaba.dubbo.config.annotation.Service;
import com.yonyou.pmclouds.ApplicationConsts;
import com.yonyou.pmclouds.basecom.billstatus.BillStatusConst;
import com.yonyou.pmclouds.basecom.consts.BillTypeConst;
import com.yonyou.pmclouds.basecom.consts.MillStoneStatusConst;
import com.yonyou.pmclouds.basecom.exception.BusinessException;
import com.yonyou.pmclouds.basecom.util.DateUtils;
import com.yonyou.pmclouds.measureindex.entity.MeasureIndexHistoryVO;
import com.yonyou.pmclouds.measureindex.mapper.MeasureIndexHisMapper;
import com.yonyou.pmclouds.milestone.service.IMilestoneQuery;
import com.yonyou.pmclouds.picture.rmiitf.PictureRemoteService;
import com.yonyou.pmclouds.plan.entity.*;
import com.yonyou.pmclouds.plan.mapper.ScheduleItemMapper;
import com.yonyou.pmclouds.plan.planindex.entity.PlanIndexVO;
import com.yonyou.pmclouds.plan.planindex.rmiitf.IPlanIndexQuery;
import com.yonyou.pmclouds.plan.rmiitf.IScheduleItemQueryService;
import com.yonyou.pmclouds.plan.rmiitf.IScheduleProgressHistoryQueryService;
import com.yonyou.pmclouds.plan.rmiitf.IScheduleProgressQueryService;
import com.yonyou.pmclouds.project.rmiitf.ProjectSimpleQuery;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.*;

/**
 * @Description: 计划任务查询类
 * @Author: zhangzhonghao
 * @Date: 2020-03-06
 */
@Service(version = ApplicationConsts.APPLICATION_VERSION, interfaceClass = IScheduleItemQueryService.class)
public class ScheduleItemQueryServiceImpl implements IScheduleItemQueryService {

    @Autowired
    private ScheduleItemMapper itemMapper;

    @Autowired
    private IPlanIndexQuery planIndexQuery;

    @Autowired
    private IScheduleProgressQueryService progressQueryService;

    @Autowired
    private ProjectSimpleQuery projectSimpleQuery;

    @Autowired
    private IMilestoneQuery milestoneQuery;

    @Autowired
    private IScheduleProgressHistoryQueryService scheduleProgressHistoryQueryService;

    @Autowired
    private MeasureIndexHisMapper measureIndexHisMapper;

    @Autowired
    private PictureRemoteService picService;

    @Override
    public List<ScheduleItemVO> queryByPkRoots(String[] pkRoots) throws BusinessException {
        List<ScheduleItemVO> itemVOS = itemMapper.queryByPkRoots(pkRoots);

        setRelatedValue(itemVOS);

        return getScheduleTreeVO(itemVOS);
    }

    @Override
    public List<ScheduleItemVO> queryByPkItems(String[] pkItems) throws BusinessException {
        if (pkItems == null || pkItems.length <= 0) {
            return new ArrayList<>();
        }

        List<ScheduleItemVO> itemVOS = itemMapper.queryByPkItems(pkItems);
        if (itemVOS == null || itemVOS.size() <= 0) {
            return new ArrayList<>();
        }

        Set<String> pkRootSet = new HashSet<>();
        for (ScheduleItemVO itemVO : itemVOS) {
            pkRootSet.add(itemVO.getPkRoot());
        }

        // 将子级信息也包含进去
        List<ScheduleItemVO> scheduleItemVOS = queryByPkRoots(pkRootSet.toArray(new String[]{}));
        Map<String, ScheduleItemVO> pkItemMap = new HashMap<>();
        for (ScheduleItemVO itemVO : scheduleItemVOS) {
            pkItemMap.put(itemVO.getPkScheduleItem(), itemVO);
        }

        List<ScheduleItemVO> result = new ArrayList<>(pkItems.length);
        for (String pkItem : pkItems) {
            result.add(pkItemMap.get(pkItem));
        }

        return result;
    }

    private List<ScheduleItemVO> getScheduleTreeVO(List<ScheduleItemVO> itemVOS) {
        Map<String, List<ScheduleItemVO>> parentVOMap = new HashMap<>();
        for (ScheduleItemVO itemVO : itemVOS) {
            List<ScheduleItemVO> itemWithParentList = parentVOMap.get(itemVO.getPkParent());
            if (itemWithParentList == null) {
                itemWithParentList = new ArrayList<>();
                parentVOMap.put(itemVO.getPkParent(), itemWithParentList);
            }
            itemWithParentList.add(itemVO);
        }

        for (ScheduleItemVO itemVO : itemVOS) {
            List<ScheduleItemVO> childItemList = parentVOMap.get(itemVO.getPkScheduleItem());
            if (childItemList != null && childItemList.size() > 0) {
                itemVO.setChildren(childItemList.toArray(new ScheduleItemVO[]{}));
                itemVO.setChildCount(childItemList.size());
            }
        }

        return itemVOS;
    }

    private void setRelatedValue(List<ScheduleItemVO> itemVOList) throws BusinessException {
        List<String> pkItemList = new ArrayList<>(itemVOList.size());
        Set<String> pkMilestoneSet = new HashSet<>();
        Map<String, ScheduleItemVO> itemVOMap = new HashMap<>();
        for (ScheduleItemVO itemVO : itemVOList) {
            pkItemList.add(itemVO.getPkScheduleItem());
            pkMilestoneSet.add(itemVO.getPkMilestone());
            itemVOMap.put(itemVO.getPkScheduleItem(), itemVO);
        }

        Map<String, List<PlanIndexVO>> planIndexMap = planIndexQuery.queryIndexOfPlans(pkItemList.toArray(new String[]{}));

        PlanProgressVO[] progressVOS = progressQueryService.queryByPkItems(pkItemList.toArray(new String[]{}));

        // 查询里程碑名称
        Map<String, String> milestoneMap = milestoneQuery.queryNameById(pkMilestoneSet.toArray(new String[0]));

        Map<String, PlanProgressVO> progressVOMap = new HashMap<>();
        if (progressVOS != null && progressVOS.length > 0) {
            for (PlanProgressVO progressVO : progressVOS) {
                progressVOMap.put(progressVO.getPkPlan(), progressVO);
            }
        }

        for (ScheduleItemVO itemVO : itemVOList) {
            List<PlanIndexVO> planIndexVOList = planIndexMap.get(itemVO.getPkScheduleItem());
            if (planIndexVOList != null && planIndexVOList.size() > 0) {
                itemVO.setPlanIndexVOs(planIndexVOList);
                itemVO.setIndexNumber(planIndexVOList.size());
            }

            PlanProgressVO progressVO = progressVOMap.get(itemVO.getPkScheduleItem());
            if (progressVO == null) {
                progressVO = new PlanProgressVO();
                progressVO.setProgress(0);
            }
            itemVO.setProgressVO(progressVO);
            itemVO.setMilestoneName(milestoneMap.get(itemVO.getPkMilestone()));

            // 添加前置计划信息
            if (StringUtils.isNotEmpty(itemVO.getDependPlan())) {
                String pkDepend = itemVO.getDependPlan();
                ScheduleItemVO dependItemVO = itemVOMap.get(pkDepend);
                if (dependItemVO != null) {
                    itemVO.setDependPlanName(dependItemVO.getCode());
                    itemVO.setDependPlans(new ScheduleItemVO[]{dependItemVO});
                }
            }

            itemVO.setKey(itemVO.getPkScheduleItem());
        }
    }

    @Override
    public Map<String, List<ScheduleItemVO>> queryByPkSchedules(String[] pkSchedules) throws BusinessException {
        List<ScheduleItemVO> itemVOS = itemMapper.queryByPkSchedules(pkSchedules);
        setRelatedValue(itemVOS);
        getScheduleTreeVO(itemVOS);

        Map<String, List<ScheduleItemVO>> itemMap = new HashMap<>();
        for (ScheduleItemVO itemVO : itemVOS) {
            List<ScheduleItemVO> itemVOListTemp = itemMap.get(itemVO.getPkSchedule());
            if (itemVOListTemp == null) {
                itemVOListTemp = new ArrayList<>();
                itemMap.put(itemVO.getPkSchedule(), itemVOListTemp);
            }
            itemVOListTemp.add(itemVO);
        }
        return itemMap;
    }

    @Override
    public Map<String, List<ScheduleItemVO>> queryByPkSchedulesOnlyRoot(String[] pkSchedules) throws BusinessException {
        Map<String, List<ScheduleItemVO>> itemMap = this.queryByPkSchedules(pkSchedules);
        for (Map.Entry<String, List<ScheduleItemVO>> entry : itemMap.entrySet()) {
            List<ScheduleItemVO> rootItemList = new ArrayList<>();
            for (ScheduleItemVO itemVO : entry.getValue()) {
                if ("~".equalsIgnoreCase(itemVO.getPkParent()) || StringUtils.isEmpty(itemVO.getPkParent())) {
                    rootItemList.add(itemVO);
                }
            }
            itemMap.put(entry.getKey(), rootItemList);
        }

        return itemMap;
    }

    @Override
    public List<ScheduleItemVO> queryByPkSchedulesOnlyEnd(String[] pkSchedules) throws BusinessException {
        List<ScheduleItemVO> itemVOS = itemMapper.queryByPkSchedules(pkSchedules);
        return itemVOS;
    }


    @Override
    public ScheduleReportVO queryByPkItem(String pkItem) throws BusinessException {

        //获取对应的任务对象
        List<ScheduleItemVO> scheduleItemVOS = itemMapper.queryByPkItems(new String[]{pkItem});

        ScheduleReportVO scheduleReportVO = new ScheduleReportVO();
        scheduleReportVO.transScheduleReportVO(scheduleItemVOS.get(0));

        //查询最后一个进度信息  再通过进度反馈记录信息 查询指标记录信息

        String[] pks = itemMapper.queryPksByPkOriginal(scheduleItemVOS.get(0).getPkOriginal());
        PlanProgressHistoryVO planProgressHistoryVO = scheduleProgressHistoryQueryService.queryLastProgressHisByPkPlans(pks);

        MeasureIndexHistoryVO[] measureIndexHistoryVOS = null;
        if (planProgressHistoryVO != null) {
            String pkProgressHis = planProgressHistoryVO.getPkProgressHis();

            //通过反馈记录主键查询指标记录
            measureIndexHistoryVOS = measureIndexHisMapper.selectMeasureIndexVOByProgressHis(pkProgressHis);
        }
        //如果是第一次反馈没有指标记录 则查计划指标项
        if (measureIndexHistoryVOS == null || measureIndexHistoryVOS.length == 0) {
            List<PlanIndexVO> planIndexVOS = planIndexQuery.queryIndexOfPlan(scheduleItemVOS.get(0).getPkScheduleItem());
            if (planIndexVOS != null || !planIndexVOS.isEmpty()) {
                MeasureIndexHistoryVO[] vos = new MeasureIndexHistoryVO[planIndexVOS.size()];
                //数据转换
                for (int i = 0; i < planIndexVOS.size(); i++) {
                    MeasureIndexHistoryVO vo = new MeasureIndexHistoryVO();
                    PlanIndexVO planIndexVO = planIndexVOS.get(i);
                    vo.setPkPlanIndex(planIndexVO.getPkPlanIndex());
                    vo.setExpectTotal(planIndexVO.getExpectTotal());
                    vo.setMeasureIndexName(planIndexVO.getName());
                    vo.setUnit(planIndexVO.getUnit());
                    vo.setPkMeasureindex(planIndexVO.getPkMeasureIndex());
                    vos[i] = vo;
                }
                measureIndexHistoryVOS = vos;
            }
        }
        //反进度信息
        if (planProgressHistoryVO != null) {
            PlanProgressVO[] planProgressVOS = progressQueryService.queryByPkItems(new String[]{planProgressHistoryVO.getPkPlan()});
            planProgressHistoryVO.setChangeFlag(planProgressVOS[0].getChangeFlag());
            scheduleReportVO.setPictures(picService.queryPicNamesByPkEntity(planProgressHistoryVO.getPkPlan()));
        }

        scheduleReportVO.setPlanProgressHistoryVO(planProgressHistoryVO);
        scheduleReportVO.setIndexHistoryVOS(measureIndexHistoryVOS);

        return scheduleReportVO;

    }

    @Override
    public Map<String, List<ScheduleItemVO>> queryChildPlanByParents(String[] pkParents) {
        ScheduleItemVO[] planVOS = itemMapper.queryChildPlanByParents(pkParents);
        if (ArrayUtils.isEmpty(planVOS))
            return new HashMap<>(0);

        Map<String, List<ScheduleItemVO>> result = new HashMap<>();
        String pkParent;
        for (ScheduleItemVO vo : planVOS) {
            pkParent = vo.getPkParent();
            if (!result.containsKey(pkParent))
                result.put(pkParent, new ArrayList<ScheduleItemVO>());

            result.get(pkParent).add(vo);
        }

        return result;
    }

    @Override
    public ScheduleItemVO[] queryByProjectAndRelatedBillType(String pkProject, String billType, String transiType) {
        List<String> billTypes = new ArrayList<>();
        billTypes.add(billType);
        // 交易类型不为空，查询关联了单据类型或交易类型的计划
        if (StringUtils.isNotEmpty(transiType)) {
            billTypes.add(transiType);
        }

        return itemMapper.queryByProjectAndRelatedBillType(pkProject, billTypes);
    }

    @Override
    public List<ScheduleItemVO> queryByProjectAndDependPlan(String pkProject, String[] dependPlans) {
        if (StringUtils.isEmpty(pkProject) || ArrayUtils.isEmpty(dependPlans))
            return new ArrayList<>(0);

        return itemMapper.queryByProjectAndDependPlan(pkProject, dependPlans);
    }

    @Override
    public MeasureIndexHistoryVO[] selectMeasureIndexVOByPlanIndex(String[] pkPlanIndex) {
        MeasureIndexHistoryVO[] measureIndexHistoryVOS = measureIndexHisMapper.selectMeasureIndexVOByPlanIndex(pkPlanIndex);
        return measureIndexHistoryVOS;
    }

    @Override
    public ScheduleItemVO[] queryByProjectAndRelatedBillType(String pkProject, String billType) throws BusinessException {

        List<String> billTypes = new ArrayList<>();
        billTypes.add(billType);

        ScheduleItemVO[] scheduleItemVOS = itemMapper.queryByProjectAndBtypeAndBstatus(pkProject, billTypes, BillStatusConst.COMMON_APPROVED_STATUS);

        if (ArrayUtils.isEmpty(scheduleItemVOS)) return new ScheduleItemVO[0];

        //设置进度
        setProgress(scheduleItemVOS);

        return scheduleItemVOS;
    }

    @Override
    public ScheduleItemVO[] queryMileStonePlan(String pkSchedule) throws BusinessException {

        ScheduleItemVO[] scheduleItemVOS = itemMapper.selectMileStonePlan(pkSchedule);
        if (ArrayUtils.isEmpty(scheduleItemVOS)) return new ScheduleItemVO[0];

        //设置进度信息
        setProgress(scheduleItemVOS);

        //设置里程碑状态
        setMileStoneStatus(scheduleItemVOS);

        //设置关联字段翻译
        setRelatedValue(Arrays.asList(scheduleItemVOS));

        return scheduleItemVOS;
    }

    /**
     * 设置里程碑状态
     * @param scheduleItemVOS
     */
    private void setMileStoneStatus(ScheduleItemVO[] scheduleItemVOS) {

        if (ArrayUtils.isEmpty(scheduleItemVOS)) return;

        for (ScheduleItemVO scheduleItemVO : scheduleItemVOS) {
            PlanProgressVO progressVO = scheduleItemVO.getProgressVO();
            if (progressVO == null || progressVO.getProgress() == 0)
                scheduleItemVO.setMilestoneStatus(MillStoneStatusConst.NOT_START);
            else if (0 < progressVO.getProgress() && progressVO.getProgress() < 100)
                scheduleItemVO.setMilestoneStatus(MillStoneStatusConst.IN_PROGRESS);
            else if (progressVO.getProgress() == 100)
                scheduleItemVO.setMilestoneStatus(MillStoneStatusConst.END);

            String milestoneStatus = scheduleItemVO.getMilestoneStatus();

            /**
             *   未开始：当前日期>计划开始日期;
             *   进行中：当前日期>计划完成日期;
             *   已完成：实际完成日期>计划完成日期；
             */
            boolean flag = false;
            Date now = new Date();
            if (MillStoneStatusConst.NOT_START.equals(milestoneStatus)) {
                flag = now.after(scheduleItemVO.getPlanStartDate());
            }
            if (MillStoneStatusConst.IN_PROGRESS.equals(milestoneStatus)) {
                flag = compareDateIngoreHMS(now, scheduleItemVO.getPlanEndDate());
            }
            if (MillStoneStatusConst.END.equals(milestoneStatus)) {
                flag = progressVO.getEndDate().after(scheduleItemVO.getPlanEndDate());
            }
            scheduleItemVO.setIsExtension(flag);
            String billType = scheduleItemVO.getRelatedBillType();

            if (!StringUtils.isEmpty(billType)) {
                if (!billType.equalsIgnoreCase(BillTypeConst.WORKSTART_BILLTYPE) && !billType.equalsIgnoreCase(BillTypeConst.COMPREHENSIVE_ACCEPTANCE_BILLTYPE)
                        && !billType.equalsIgnoreCase(BillTypeConst.WORKSTART_BILLTYPE)) {
                    scheduleItemVO.setIsNcBill(true);
                }
            }
        }
    }
    /**
     * 设置进度信息
     *
     * @param scheduleItemVOS
     * @throws BusinessException
     */
    private void setProgress(ScheduleItemVO[] scheduleItemVOS) throws BusinessException {
        HashMap<String, ScheduleItemVO> data = new HashMap<>();
        for (ScheduleItemVO scheduleItemVO : scheduleItemVOS) {
            data.put(scheduleItemVO.getPkScheduleItem(), scheduleItemVO);
        }

        PlanProgressVO[] planProgressVOS = progressQueryService.queryByPkItems(data.keySet().toArray(new String[0]));

        if (ArrayUtils.isEmpty(planProgressVOS)) return;
        for (PlanProgressVO planProgressVO : planProgressVOS) {
            data.get(planProgressVO.getPkPlan()).setProgressVO(planProgressVO);
        }
    }

    /**
     * @param date
     * @param targetDate
     * @return 比较时间大小
     */
    private boolean compareDateIngoreHMS(Date date, Date targetDate) {
        Calendar cal1 = Calendar.getInstance();
        cal1.setTime(date);
        // 将时分秒,毫秒域清零
        cal1.set(Calendar.HOUR_OF_DAY, 0);
        cal1.set(Calendar.MINUTE, 0);
        cal1.set(Calendar.SECOND, 0);
        cal1.set(Calendar.MILLISECOND, 0);
        return cal1.getTimeInMillis() > targetDate.getTime();
    }
}
